﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://wpfimageviewer.codeplex.com
using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Controls;
using System.Windows.Threading;
using BrainTechLLC;
using BrainTechLLC.WPF;
using ImageAppViewModels;
using System.ComponentModel;

namespace WpfImageDuplicates
{
    public partial class ImageCollectionView : UserControl
    {
        public Thread _SortThread;
        Action<SortInfo> _WhenDone;
        Dictionary<string, int> _FileNameInPosition;

        public void SortAll(bool userInitiated)
        {
            try
            {
                List<FileImageViewModel> vmList = null;
                Window1._doNotStartFileImageCollectionDirectoryReader = true;

                if (userInitiated && Settings.Values.OrderedFileNames.Count > 0 &&
                    (((_lastSort != Settings.Values.SortBy || (_lastDirection == ListSortDirection.Descending) != Settings.Values.SortDescending)) ||
                    ((_lastSort2 != Settings.Values.SortBy2 || (_lastDirection2 == ListSortDirection.Descending) != Settings.Values.SortDescending2))))
                {
                    Settings.Values.OrderedFileNames.Clear();
                }

                if (!userInitiated)
                {
                    if (Settings.Values.OrderedFileNames.Count > 0)
                    {
                        vmList = _vm.ToList();
                        string key = DirectoryToExamine == null ? "*" : DirectoryToExamine.Directory;
                        SortInfo sortInfo = new SortInfo() { directoryToExamine = key, vmList = vmList };

                        _WhenDone = new Action<SortInfo>(info =>
                        {
                            Dispatcher.BeginInvoke(() =>
                            {
                                var lastSelected = _lastSelected;
                                Window1.MainWindow.CollectionViews = null;

                                Window1.MainWindow._AllFileImageCollectionViewModels.ForEach(o =>
                                {
                                    o._fileImageCollection.ClearAllItems();                                        
                                });
                                Window1.MainWindow.ClearFileImageCollections();
                                Window1.MainWindow._FileImageCollectionViewModels = null;

                                for (int n = 0; n < Window1.MainWindow.CollectionViews.Count; n++)
                                {
                                    var collectionView = Window1.MainWindow.CollectionViews[n];
                                    var fileImages = Window1.MainWindow.FileImageCollectionViewModels[n];

                                    collectionView.FileImageCollectionViewModel = fileImages;
                                    collectionView._HasSorted = true;
                                    vmList.ForEach(o => fileImages.AddByFileName(o.FileName));
                                    collectionView.AddListItems(vmList);
                                }
                                _lastSelected = lastSelected;

                                Settings.Values.OrderedFileNames.Clear();

                                SelectLastSelected();
                            });
                        });

                        CreateThreadSortByOrderedFileNamesIfNotExists(sortInfo);
                    }
                }
                else if (Settings.Values.OrderedFileNames.Count == 0)
                {
                    if (((_lastSort != Settings.Values.SortBy || (_lastDirection == ListSortDirection.Descending) != Settings.Values.SortDescending)) ||
                        ((_lastSort2 != Settings.Values.SortBy2 || (_lastDirection2 == ListSortDirection.Descending) != Settings.Values.SortDescending2)))
                    {
                        _lastDirection = Settings.Values.SortDescending ? ListSortDirection.Descending : ListSortDirection.Ascending;
                        _lastSort = Settings.Values.SortBy;
                        _lastDirection2 = Settings.Values.SortDescending2 ? ListSortDirection.Descending : ListSortDirection.Ascending;
                        _lastSort2 = Settings.Values.SortBy2;

                        if (_vm != null)
                        {
                            vmList = _vm.ToList();

                            string key = DirectoryToExamine == null ? "*" : DirectoryToExamine.Directory;
                            SortInfo sortInfo = new SortInfo() { directoryToExamine = key, vmList = vmList };
                            Settings.Values.OrderedFileNames.Remove(key, s => true);
                            FileImageCollectionViewModel.ForEach(o => o._DesiredOrdering = 0);

                            _WhenDone = new Action<SortInfo>(info =>
                            {
                                Dispatcher.BeginInvoke(() =>
                                {
                                    Settings.Values.OrderedFileNames.Remove(key, s => true);
                                    Settings.Values.SaveOrdering(info.vmList, key, fi => fi.FileName, Settings.Values.OrderedFileNames);
                                    _OrderedFileNames = Settings.Values.OrderedFileNames;

                                    Window1.MainWindow._AllFileImageCollectionViewModels.ForEach(o => o._fileImageCollection.ClearAllItems());
                                    Window1.MainWindow.ClearFileImageCollections();
                                    Window1.MainWindow._FileImageCollectionViewModels = null;
                                    Window1.MainWindow.CollectionViews = null;

                                    for (int n = 0; n < Window1.MainWindow.CollectionViews.Count; n++)
                                    {
                                        var collectionView = Window1.MainWindow.CollectionViews[n];
                                        var fileImages = Window1.MainWindow.FileImageCollectionViewModels[n];
                                        collectionView.FileImageCollectionViewModel = fileImages;
                                        collectionView._HasSorted = true;
                                        info.vmList.ForEach(o => fileImages.AddByFileName(o.FileName));
                                    }

                                    SelectLastSelected();
                                });
                            });

                            CreateThreadSortBySettingsValuesIfNotExists(sortInfo);
                        }
                        else
                        {
                            vmList = Displayed.ToList();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        private void SelectLastSelected()
        {
            if (_lastSelected != null)
            {
                var vmSelected = _lastSelected;

                Dispatcher.BeginInvoke(new OneParamDelegate((o) =>
                {
                    var lastSelected = o as FileImageViewModel;

                    var thumbView = Window1.MainWindow.CollectionViews.FindThumbView(lastSelected._fileName);

                    if (thumbView != null)
                    {
                        for (int n = 0; n < Window1.MainWindow.CollectionViews.Count; n++)
                        {
                            var collectionView = Window1.MainWindow.CollectionViews[n];
                            int idx = collectionView.Displayed.GetIndex(lastSelected._fileName);
                            if (idx >= 0)
                            {
                                collectionView.SelectAndMoveTo(0, idx, System.Windows.Input.ModifierKeys.None);
                            }
                            collectionView._lastSelected = lastSelected;
                        }
                    }
                }), DispatcherPriority.ApplicationIdle, vmSelected);
            }
        }

        private void CreateThreadSortByOrderedFileNamesIfNotExists(SortInfo sortInfo)
        {
            if (_SortThread == null)
            {
                lock (_lockObject)
                {
                    if (_SortThread == null)
                    {
                        ParameterizedThreadStart ts = new ParameterizedThreadStart(DoSort);
                        _SortThread = ts.CreateAndRunThread(true, sortInfo);
                    }
                }
            }
        }

        private void CreateThreadSortBySettingsValuesIfNotExists(SortInfo sortInfo)
        {
            if (_SortThread == null)
            {
                lock (_lockObject)
                {
                    if (_SortThread == null)
                    {
                        ParameterizedThreadStart ts = new ParameterizedThreadStart(DoSortBySettingsValues);
                        _SortThread = ts.CreateAndRunThread(true, sortInfo);
                    }
                }
            }
        }

        private void DoSortBySettingsValues(object o)
        {
            SortInfo sortInfo = o as SortInfo;
            sortInfo.vmList = Window1.SortBySettingValues(sortInfo.vmList);
            if (_WhenDone != null)
            {
                _WhenDone(sortInfo);
            }
            _SortThread = null;
        }

        private void DoSort(object o)
        {
            SortInfo sortInfo = o as SortInfo;
            SortByOrderedFileNames(sortInfo.directoryToExamine, sortInfo.vmList);
            if (_WhenDone != null)
            {
                _WhenDone(sortInfo);
            }
            _SortThread = null;
        }

        private void SortByOrderedFileNames(string directoryToExamine, List<FileImageViewModel> vmList)
        {
            var list = Settings.Values.OrderedFileNames[directoryToExamine];
            int count = vmList.Count;

            _FileNameInPosition = new Dictionary<string, int>();
            for (int n = 0; n < list.Count; n++)
            {
                var fileName = list[n];
                _FileNameInPosition.Add(fileName.FileName, n);
            }
            vmList.ForEach(o =>
            {
                int idx1 = count;
                _FileNameInPosition.TryGetValue(o.FileName, out idx1);
                o._DesiredOrdering = idx1 + 1;
            });

            vmList.Sort(new Comparison<FileImageViewModel>((fi1, fi2) => fi1._DesiredOrdering.CompareTo(fi2._DesiredOrdering)));
        }

        public void Filter(List<FileImageViewModel> itemsToInclude)
        {
            Window1.MainWindow.CollectionViews = null;
            Window1.MainWindow._AllFileImageCollectionViewModels.ForEach(o => o._fileImageCollection.ClearAllItems());
            Window1.MainWindow.ClearFileImageCollections();
            Window1.MainWindow._FileImageCollectionViewModels = null;

            for (int n = 0; n < Window1.MainWindow.CollectionViews.Count; n++)
            {
                bool noFilter = (string.IsNullOrEmpty(Settings.Values.FileNameFilter) && Settings.Values.MinSizeFilter <= 0 && (Settings.Values.MaxSizeFilter == 0 || Settings.Values.MaxSizeFilter >= Int32.MaxValue - 1) && !Window1.MainWindow.AllGroups.ShowOnlySelectedGroups);
                if (!noFilter)
                {
                    Window1._doNotStartFileImageCollectionDirectoryReader = true;
                }
                var collectionView = Window1.MainWindow.CollectionViews[n];
                var fileImages = Window1.MainWindow.FileImageCollectionViewModels[n];
                // HEREHERE
                fileImages.Clear();
                collectionView.FileImageCollectionViewModel = fileImages;
                collectionView._HasSorted = true;
                collectionView._itemsAdded.Clear();
                itemsToInclude.ForEach(o => fileImages.AddByFileName(o.FileName));
                collectionView.AddListItems(itemsToInclude);
                if (!noFilter)
                {
                    Window1._doNotStartFileImageCollectionDirectoryReader = false;
                }
            }
        }

    }

    public class SortInfo
    {
        public string directoryToExamine;
        public List<FileImageViewModel> vmList;
    }
}